package classes;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

/**
 * QRImage.java
 * 
 * @author Nicole Nelson
 */
public class QRImage 
{
	private BufferedImage modified;
	private BufferedImage original;
	private int BLACK = -16777216;
	private int WHITE = -1;
	private int THRESHOLD;
	private boolean display;
	
	/*
	 * Constructor: Opens the image at the specified filename
	 */
	public QRImage(String fileName)
	{
		//Get Image from file
		try
		{
			original = ImageIO.read(new File(fileName));
			modified = original;
		}
		catch (IOException e)
		{
			System.out.println("Unable to Read File");
			System.exit(0);
		}

	}
	
	public void setDisplay(boolean dis)
	{
		display = dis;
	}
	
	/*
	 * Returns the Original image
	 */
	public BufferedImage getOriginalImage()
	{
		return original;
	}
	
	/*
	 * Sets the Modified Image
	 */
	public void setModifiedImage(BufferedImage o) 
	{
		modified = o;
	}

	/*
	 * Sets the threshold based on the average pixel color
	 */
	public void setThreshold(BufferedImage image)
	{
		double sum = 0;
		int imgWidth = image.getWidth();
		int imgHeight = image.getHeight();
		int totalPixels = imgWidth * imgHeight;
		
		for (int width = 0; width < imgWidth; width++)
			for (int height = 0; height < imgHeight; height++)
				sum += image.getRGB(width, height);
				
		THRESHOLD = (int) (sum / totalPixels);
	}
	
	
	/*
	 * Returns a binary image of the original picture using a thresholding technique
	 */
	public BufferedImage myGray()
	{
		//Changes the image to gray scale
		BufferedImage gray = new BufferedImage(modified.getWidth(), modified.getHeight(), BufferedImage.TYPE_INT_ARGB);
		int imgWidth = modified.getWidth();
		int imgHeight = modified.getHeight();
		
		for (int width = 0; width < imgWidth; width++)
			for (int height = 0; height < imgHeight; height++)
			{
				int rgb = modified.getRGB(width, height);
				int red = (rgb >> 16) & 0xFF;
				int green = (rgb >> 8) & 0xFF;
				int blue = (rgb) & 0xFF;
				int grayScale = (int) (0.3 * red + 0.59 * green + 0.11 * blue);
				gray.setRGB(width, height, grayScale);
			}
		
		setThreshold(gray);
		
		//If the pixel is less than the Threshold change it to black otherwise its white
		imgWidth = gray.getWidth();
		imgHeight = gray.getHeight();
		
		for (int width = 0; width < imgWidth; width++)
			for (int height = 0; height < imgHeight; height++)
			{
				if (gray.getRGB(width, height) < THRESHOLD)
					gray.setRGB(width, height, BLACK);
				else
					gray.setRGB(width, height, WHITE);
			}
		
		return gray;
	}
	
	/*
	 * This function will use the original image to find the QRCode that is in it
	 */
	public QRCode findCode()
	{
		
		QRCode result = new QRCode();
		result.display = display;
		//Gets an image with some noise reduction
		setModifiedImage((new NoiseReduction()).reduceNoise(myGray()));
		
		//Gets the edgeDetection of the Image to help find the skew
		EdgeDetection edge = new EdgeDetection();
		double angle = new Rotation().findAngle(modified);
		edge.setOriginal((new Rotation()).rotation(modified, angle));
		
		//Gets the final cropped image of where the QR Code is suspected to be
		setModifiedImage(edge.crop());

		//Finds the finder patterns and makes sure the qr code is in the correct rotation
		FindPattern f = new FindPattern();
		result.setCode(f.findCorrectRotation(modified));
		
		//Decodes the qr code into a boolean array
		result.DecodeCode();
		
		
		
		return result;
	}
}
